//package qj.tool.volatileidexim;
//
//import java.io.InputStream;
//import java.io.InputStreamReader;
//import java.nio.charset.Charset;
//import java.util.HashMap;
//import java.util.LinkedList;
//import java.util.zip.ZipInputStream;
//
//import qj.tool.volatileidexim.VolatileIdEximConfig.ConfigType;
//import qj.util.IOUtil;
//import qj.util.ZipUtil;
//import qj.util.funct.F1;
//import qj.util.funct.P1;
//import qj.util.funct.P2;
//
//import com.google.gson.Gson;
//
//@SuppressWarnings("rawtypes")
//public class VolatileIdImporter {
//	VolatileIdEximConfig config;
//	public VolatileIdImporter(VolatileIdEximConfig config) {
//		this.config = config;
//	}
//	
//	public void doImport(InputStream in) {
//		System.out.println("Start importing");
//		config.beforeImport.e();
//		
//		// Store id map
//		final HashMap idMap = new HashMap();
//		
//		// Store pending objects for change ids
//		final LinkedList<Recheck> pendingRechecks = new LinkedList<Recheck>();
//		
//		// Load the objects from external storage
//		loadImportingFromExternal(in, new P1<Importing>() {public void e(Importing importing) {
//			Object oldId = importing.getId();
//			
//			// Save to db
//			Object newId = importing.saveToDB();
//			
////			System.out.println("oldId=" + oldId + ", newId=" + newId);
//			
//			// Store new id in id map
//			idMap.put(oldId, newId);
//			
//			// Check if this object needs to be checked again
//			Recheck recheck = importing.getRecheck();
//			
//			// Add to pending recheck list
//			if (recheck != null) {
//				pendingRechecks.add(recheck);
//			}
//		}});
//		
//		System.out.println("Has " + pendingRechecks.size() + " pending objects for recheck");
//		
//		// With each pending objects
//		for (; !pendingRechecks.isEmpty();) {
//			Recheck recheck = pendingRechecks.removeFirst();
//			// Load from db
//			recheck.load();
//			
//			// Set new ids by the map
//			recheck.resetLinkedIds(new F1<Object,Object>() {public Object e(Object holdingId) {
//				if (holdingId==null) {
//					return null;
//				}
//				
//				final Object newId = idMap.get(holdingId);
//				if (newId==null) {
//					System.out.println("Can not find new id of " + holdingId);
//				}
//				return newId;
//			}});
//			
//			// Save again into db
//			recheck.save();
//		}
//		
//		config.afterImport.e();
//		System.out.println("Done importing");
//	}
//	
//	@SuppressWarnings("unchecked")
//	public void loadImportingFromExternal(InputStream in, final P1<Importing> p1) {
//		final Gson gson = config.gsonBuilder.create();
//		ZipUtil.eachEntry(new ZipInputStream(in), new P2<String, InputStream>() {public void e(String fileName, InputStream in) {
//			String typeName = fileName.replaceAll("\\.json$", "");
//			final ConfigType configType = config.types.get(typeName);
//			IOUtil.eachMarkedLines("<END>", new InputStreamReader(in, Charset.forName("UTF-8")), new P1<String>() {public void e(String lines) {
//				Object model = gson.fromJson(lines, configType.clazz);
//				p1.e(createImporting(configType, model));
//			}});
//		}});
//	}
//
//	private <T,K> Importing<T,K> createImporting(ConfigType<T, K> configType,
//			T model) {
//		return new Importing<T, K>(model, config.saveF, config.updateF, configType.getIdF, configType.refFix, configType.getF);
//	}
//	
//	/**
//	 * Represent 1 object to be imported
//	 * @author quanle
//	 *
//	 */
//	static class Importing<T,K> {
//		final T model;
//		private P1<T> saveF;
//		F1<K,T> getF;
//		F1<T,K> getIdF;
//		private P2<T, F1<K,K>> refFix;
//		private P1<T> updateF;
//		
//		public Importing(T model, P1<T> saveF, P1<T> updateF, F1<T,K> getIdF, P2<T, F1<K,K>> refFix, F1<K,T> getF) {
//			this.model = model;
//			this.saveF = saveF;
//			this.updateF = updateF;
//			this.getIdF = getIdF;
//			this.refFix = refFix;
//			this.getF = getF;
//		}
//		
//		public Object saveToDB() {
//			saveF.e(model);
//			return getId();
//		}
//
//		public Recheck getRecheck() {
//			if (refFix==null) {
//				return null;
//			}
//			return new Recheck(getId(), getF, updateF, refFix);
//		}
//
//		public Object getId() {
//			return getIdF.e(model);
//		}
//		
//	}
//	
//	static class Recheck<T,K> {
//		final K newId;
//		F1<K,T> getF;
//		P1<T> saveF;
//		
//		T model = null;
//		private P2<T, F1<K,K>> refFix;
//		
//		public Recheck(K newId, F1<K,T> getF, P1<T> saveF, P2<T, F1<K,K>> refFix) {
//			this.newId = newId;
//			this.getF = getF;
//			this.saveF = saveF;
//			this.refFix = refFix;
//		}
//		
//		public void load() {
//			model = getF.e(newId);
//		}
//
//		public void resetLinkedIds(F1 oldNewIdMap) {
//			refFix.e(model, oldNewIdMap);
//		}
//
//		public void save() {
//			saveF.e(model);
//		}
//		
//	}
//}
